home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / prog / graphics / sweep_segments.c < prev    next >
C/C++ Source or Header  |  1994-08-05  |  21KB  |  945 lines

  1. #include <LEDA/prio.h>
  2. #include <LEDA/sortseq.h>
  3. #include <LEDA/segment.h>
  4. #include <LEDA/window.h>
  5.  
  6. #include <math.h>
  7.  
  8.  
  9.  
  10. /*
  11. #include <LEDA/graph.h>
  12.  
  13. */
  14.  
  15.  
  16.  
  17. #define EPS  0.00001
  18. #define EPS2 0.0000000001
  19.  
  20.  
  21. window* Wp;
  22.  
  23. static bool trace = false;
  24. static bool intera = false;
  25. static color seg_color = blue;
  26. static color node_color = red;
  27.  
  28.  
  29. class SWEEP_POINT;
  30. class SWEEP_SEGMENT;
  31. typedef SWEEP_POINT* SWEEP_point;
  32. typedef SWEEP_SEGMENT* SWEEP_segment;
  33.  
  34. enum SWEEP_point_type {Cross=0,Rightend=1,Leftend=2}; 
  35.  
  36.  
  37. class SWEEP_POINT
  38. {
  39.   friend class SWEEP_SEGMENT;
  40.  
  41.   SWEEP_segment seg;
  42.   int     kind;
  43.   double    x,y;
  44.  
  45.   public:
  46.  
  47.   SWEEP_POINT(double a,double b)   { x=a; y=b; seg=0; kind=Cross;}
  48.  
  49.   SWEEP_POINT(point p)         { x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;}
  50.  
  51.   friend double    get_x(SWEEP_point p);
  52.   friend double    get_y(SWEEP_point p);
  53.   friend int       get_kind(SWEEP_point p);
  54.   friend SWEEP_segment get_seg(SWEEP_point p);
  55.  
  56.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  57.  
  58.   LEDA_MEMORY(SWEEP_POINT);
  59.  
  60. };
  61.  
  62.   inline double    get_x(SWEEP_point p)       { return p->x; }
  63.   inline double    get_y(SWEEP_point p)       { return p->y; }
  64.   inline int       get_kind(SWEEP_point p)    { return p->kind; }
  65.   inline SWEEP_segment get_seg(SWEEP_point p) { return p->seg; }   
  66.  
  67.  
  68. int compare(const SWEEP_point& p1, const SWEEP_point& p2)
  69. { if (p1==p2) return 0;
  70.  
  71.   double diffx = get_x(p1) - get_x(p2);
  72.   if (fabs(diffx) > EPS2 ) return (diffx > 0.0) ? 1 : -1;
  73.  
  74.   int  diffk = get_kind(p1)-get_kind(p2);
  75.   if (diffk != 0) return diffk;
  76.  
  77.   double diffy = get_y(p1) - get_y(p2);
  78.   if (fabs(diffy) > EPS2 ) return (diffy > 0.0) ? 1 : -1;
  79.  
  80.   return 0;
  81.  
  82. }
  83.  
  84. void Print(SWEEP_point& p) { cout << string("(%f,%f)",get_x(p), get_y(p)); }
  85.  
  86.  
  87.  
  88.  
  89. class SWEEP_SEGMENT
  90. {
  91.   SWEEP_point startpoint;
  92.   SWEEP_point endpoint;
  93.   double  slope;
  94.   double  yshift;
  95.   //node  left_node;
  96.   int   orient;
  97.   int   color;
  98.   int   name;
  99.  
  100.   public:
  101.  
  102.   SWEEP_SEGMENT(SWEEP_point, SWEEP_point,int,int);     
  103.  ~SWEEP_SEGMENT() { delete startpoint; delete endpoint; }     
  104.  
  105.   friend SWEEP_point get_startpoint(SWEEP_segment seg);
  106.   friend SWEEP_point get_endpoint(SWEEP_segment seg);
  107.   friend double get_slope(SWEEP_segment seg);
  108.   friend double get_yshift(SWEEP_segment seg);
  109.   friend int  get_orient(SWEEP_segment seg);
  110.   friend int  get_color(SWEEP_segment seg);
  111.   friend int  get_name(SWEEP_segment seg);
  112.  
  113. /*
  114.   friend node get_left_node(SWEEP_segment seg)         { return seg->left_node;}
  115.   friend void set_left_node(SWEEP_segment seg, node v) { seg->left_node = v; }
  116. */
  117.  
  118.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  119.  
  120.   LEDA_MEMORY(SWEEP_SEGMENT);
  121.  
  122.  
  123. };
  124.  
  125.  
  126. inline SWEEP_point get_startpoint(SWEEP_segment seg) { return seg->startpoint; }
  127. inline SWEEP_point get_endpoint(SWEEP_segment seg)   { return seg->endpoint; }
  128. inline double get_slope(SWEEP_segment seg)           { return seg->slope; }
  129. inline double get_yshift(SWEEP_segment seg)          { return seg->yshift; }
  130. inline int  get_orient(SWEEP_segment seg)            { return seg->orient; }
  131. inline int  get_color(SWEEP_segment seg)             { return seg->color; }
  132. inline int  get_name(SWEEP_segment seg)              { return seg->name; }
  133.  
  134.  
  135.   SWEEP_SEGMENT::SWEEP_SEGMENT(SWEEP_point p1,SWEEP_point p2,int c, int n)    
  136.   {
  137.     //left_node  = nil;
  138.     color      = c;
  139.     name       = n;
  140.  
  141.     if (compare(p1,p2) < 0)
  142.      { startpoint = p1; 
  143.        endpoint = p2; 
  144.        orient = 0;
  145.       }
  146.     else
  147.      { startpoint = p2; 
  148.        endpoint = p1; 
  149.        orient = 1;
  150.       }
  151.  
  152.     startpoint->kind = Leftend; 
  153.     endpoint->kind = Rightend; 
  154.     startpoint->seg = this; 
  155.     endpoint->seg = this;
  156.  
  157.     if (endpoint->x != startpoint->x)
  158.     {
  159.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  160.       yshift = startpoint->y - slope * startpoint->x;
  161.  
  162.       startpoint->x -= EPS;
  163.       startpoint->y -= EPS * slope;
  164.       endpoint->x += EPS;
  165.       endpoint->y += EPS * slope;
  166.     }
  167.     else //vertical segment
  168.     { startpoint->y -= EPS;
  169.       endpoint->y   += EPS;
  170.      }
  171.   }
  172.  
  173. void Print(SWEEP_segment& s) { cout << string("S%d",get_name(s)); }
  174.  
  175. static double x_sweep;
  176. static double y_sweep;
  177.  
  178.  
  179. int compare(const SWEEP_segment& s1,const SWEEP_segment& s2)
  180. {
  181.   double sl1 = get_slope(s1);
  182.   double sl2 = get_slope(s2);
  183.   double ys1 = get_yshift(s1);
  184.   double ys2 = get_yshift(s2);
  185.  
  186.   double y1 = sl1*x_sweep+ys1;
  187.   double y2 = sl2*x_sweep+ys2;
  188.  
  189.   double diff = y1-y2;
  190.  
  191.   if (fabs(diff) > EPS2) return (diff > 0.0) ? 1 : -1;
  192.  
  193.   if (sl1 == sl2) 
  194.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  195.  
  196.     if (y1 <= y_sweep+EPS2)
  197.         return compare(sl1,sl2);
  198.     else
  199.         return compare(sl2,sl1);
  200.  
  201. }
  202.  
  203.  
  204.  
  205.  
  206. static priority_queue<seq_item,SWEEP_point> X_structure;
  207.  
  208. static sortseq<SWEEP_segment,pq_item> Y_structure;
  209.  
  210.  
  211. bool intersection(SWEEP_segment seg1,SWEEP_segment seg2, SWEEP_point& inter)
  212. {
  213.   if (seg1->slope == seg2->slope)
  214.     return false;
  215.   else
  216.   {
  217.     //x-coordinate  of the intersection
  218.     double Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  219.  
  220.     if (Cross_x <= x_sweep) return false;
  221.  
  222.     double s1 = seg1->startpoint->x;
  223.     double s2 = seg2->startpoint->x;
  224.     double e1 = seg1->endpoint->x;
  225.     double e2 = seg2->endpoint->x;
  226.  
  227.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  228.  
  229.     //y-coordinate of the intersection
  230.     double Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  231.     inter =  new SWEEP_POINT(Cross_x,Cross_y);
  232.  
  233.     return true;
  234.   }
  235. }
  236.  
  237. void message(string s, int line=1)
  238. { s += "                                                            ";
  239.   double d = 20/Wp->scale();
  240.   if (s.length() > 150) s = s.head(150);
  241.   Wp->draw_text(Wp->xmin()+d, Wp->ymax()-d*(0.5+line),s);
  242.  }
  243.  
  244.  
  245. void draw_segment(SWEEP_segment seg)
  246. { double x1 = get_x(get_startpoint(seg));
  247.   double y1 = get_y(get_startpoint(seg));
  248.   double x2 = get_x(get_endpoint(seg));
  249.   double y2 = get_y(get_endpoint(seg));
  250.  
  251.   double d = 10/Wp->scale();
  252.  
  253.   Wp->draw_text(x1-d,y1,string("%d",get_name(seg)));
  254.  
  255.   Wp->draw_segment(x1,y1,x2,y2,seg_color);
  256. }
  257.  
  258.  
  259.  
  260.  
  261. void draw_sweep_line(double xpos) 
  262. {
  263.   Wp->set_mode(xor_mode);
  264.   Wp->draw_segment(xpos,-1150,xpos,Wp->ymax()-5*20/Wp->scale());
  265.   Wp->set_mode(src_mode);
  266. }
  267.  
  268.  
  269. void move_sweep_line(double x, double xpos) 
  270.   if (x == xpos) return;
  271.  
  272.   double delta = 1/Wp->scale(); 
  273.   double y = Wp->ymax()-100*delta;
  274.  
  275.   Wp->set_mode(xor_mode);
  276.  
  277.   while (x < xpos)
  278.   { Wp->draw_segment(x+delta,-1150,x+delta,y);
  279.     Wp->draw_segment(x,-1150,x,y);
  280.     x += delta;
  281.    }
  282.   
  283.   Wp->draw_segment(x,-1150,x,y);
  284.   Wp->draw_segment(xpos,-1150,xpos,y);
  285.  
  286.   Wp->set_mode(src_mode);
  287. }
  288.  
  289.  
  290.  
  291. void draw_Ystructure()
  292. {
  293.   seq_item sit;
  294.   string s = "Y_structure: ";
  295.  
  296.   forall_items(sit,Y_structure) 
  297.     s+=string("%d ",get_name(Y_structure.key(sit)));
  298.  
  299.   message(s,3);
  300.  
  301. }
  302.  
  303. void draw_Xstructure()
  304. {
  305.   string s = "X_structure: ";
  306.  
  307.   priority_queue<seq_item,SWEEP_point> Q = X_structure;
  308.  
  309.   while (!Q.empty())
  310.   { pq_item it = Q.find_min(); 
  311.  
  312.     SWEEP_point p = X_structure.inf(it);
  313.     seq_item sit  = X_structure.key(it);
  314.  
  315.     Q.del_min();
  316.  
  317.      SWEEP_segment seg = get_seg(p);
  318.  
  319.      switch (get_kind(p)) {
  320.  
  321.      case Leftend:  s += string("L(%d) ",get_name(seg));
  322.                     break;
  323.  
  324.      case Rightend: s += string("R(%d) ",get_name(seg)) ;
  325.                     break;
  326.  
  327.      default:       s += string("X(%d) ",get_name(Y_structure.key(sit))); 
  328.                     break;
  329.  
  330.      }
  331.  
  332.   }
  333.  
  334.   message(s,2);
  335.  
  336. }
  337.  
  338. pq_item Xinsert(seq_item i, SWEEP_point p) 
  339.  
  340.  if (trace)
  341.  {
  342.   SWEEP_segment s ;
  343.   if (i!=nil) s = Y_structure.key(i);
  344.  
  345.   else s = get_seg(p);
  346.     
  347.      switch (get_kind(p)) {
  348.  
  349.      case Leftend:  message(string("Xinsert: L(%d) ",get_name(s)),4);
  350.                     break;
  351.  
  352.      case Rightend: message(string("Xinsert: R(%d) ",get_name(s)),4) ;
  353.                     break;
  354.  
  355.      default:       message(string("Xinsert: X(%d) ",get_name(s)),4); 
  356.                     break;
  357.       }
  358.  
  359.   Wp->set_mode(xor_mode);
  360.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  361.   Wp->set_mode(src_mode);
  362.  }
  363.   return X_structure.insert(i,p);
  364. }
  365.  
  366. SWEEP_point Xdelete(pq_item i) 
  367. {
  368.  if (trace)
  369.  {SWEEP_point p = X_structure.inf(i);
  370.  
  371.   seq_item sit = X_structure.key(i);
  372.  
  373.   SWEEP_segment s ;
  374.  
  375.   if (sit!=nil) s = Y_structure.key(sit);
  376.   else s = get_seg(p);
  377.     
  378.      switch (get_kind(p)) {
  379.  
  380.      case Leftend:  message(string("Xdelete: L(%d) ",get_name(s)),4);
  381.                     break;
  382.  
  383.      case Rightend: message(string("Xdelete: R(%d) ",get_name(s)),4) ;
  384.                     break;
  385.  
  386.      default:       message(string("Xdelete: X(%d) ",get_name(s)),4); 
  387.                     break;
  388.       }
  389.  
  390.   Wp->set_mode(xor_mode);
  391.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  392.   Wp->set_mode(src_mode);
  393.  }
  394.  
  395.   SWEEP_point p = X_structure.inf(i);
  396.  
  397.   X_structure.del_item(i);
  398.  
  399.   return p;
  400. }
  401.  
  402.  
  403.  
  404. /*
  405. node New_Node(GRAPH<point,int>& G,double x, double y )
  406. { return G.new_node(point(x,y)); }
  407.  
  408. void New_Edge(GRAPH<point,int>& G,node v, node w, SWEEP_segment l )
  409. { if (get_orient(l)==0)
  410.        G.new_edge(v,w,get_color(l));
  411.   else G.new_edge(w,v,get_color(l));
  412. }
  413. */
  414.  
  415.  
  416. void process_vertical_segment(/*GRAPH<point,int>& SUB, */ SWEEP_segment l)
  417.   SWEEP_point p = 
  418.               new SWEEP_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  419.   SWEEP_point q = 
  420.               new SWEEP_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  421.  
  422.   SWEEP_point r = new SWEEP_POINT(get_x(p)+1,get_y(p));
  423.   SWEEP_point s = new SWEEP_POINT(get_x(q)+1,get_y(q));
  424.  
  425.   SWEEP_segment bot = new SWEEP_SEGMENT(p,r,0,0);
  426.   SWEEP_segment top = new SWEEP_SEGMENT(q,s,0,0);
  427.  
  428.   seq_item bot_it = Y_structure.insert(bot,nil);
  429.   seq_item top_it = Y_structure.insert(top,nil);
  430.   seq_item sit;
  431.  
  432.   //node u,v,w;
  433.  
  434.   SWEEP_segment seg;
  435.   
  436.  
  437.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  438.   { seg = Y_structure.key(sit);
  439.  
  440.     double cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  441.  
  442.     Wp->draw_filled_node(get_x(p),cross_y,node_color);
  443.  
  444. /*
  445.     v = get_left_node(seg);
  446.     if (v==nil)
  447.     { w = New_Node(SUB,get_x(p),cross_y);
  448.       set_left_node(seg,w);
  449.      }
  450.     else
  451.     { double vx = SUB[v].xcoord();
  452.       if ( vx < get_x(p)-EPS2) 
  453.       { w = New_Node(SUB,get_x(p),cross_y);
  454.         New_Edge(SUB,v,w,seg);
  455.         set_left_node(seg,w);
  456.        }
  457.       else w = v;
  458.      }
  459.  
  460.     u = get_left_node(l);
  461.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  462.     set_left_node(l,w);
  463. */
  464.  
  465.    }
  466.     
  467.   delete l;
  468.   delete bot;
  469.   delete top;
  470.   Y_structure.del_item(bot_it);
  471.   Y_structure.del_item(top_it);
  472.  
  473.  }
  474.  
  475.  
  476. void plane_sweep(list<segment>& L1, list<segment>& L2 
  477.                  /*, GRAPH<point,int>& SUB */)
  478. {
  479.   SWEEP_point    p,inter;
  480.   SWEEP_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  481.  
  482.   pq_item  pqit,pxmin;
  483.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  484.  
  485.  
  486.   int count=1;
  487.  
  488.   Wp->clear();
  489.  
  490.   //initialization of the X-structure
  491.  
  492.   segment s;
  493.  
  494.   forall(s,L1) 
  495.    { SWEEP_point p = new SWEEP_POINT(s.start());
  496.      SWEEP_point q = new SWEEP_POINT(s.end());
  497.      seg = new SWEEP_SEGMENT(p,q,0,count++);
  498.      draw_segment(seg);
  499.      Xinsert(nil,get_startpoint(seg));
  500. /*
  501. Print(seg);
  502. Print(get_startpoint(seg));
  503. newline;
  504. */
  505.    }
  506.  
  507.   count = -1;
  508.  
  509.   forall(s,L2) 
  510.    { SWEEP_point p = new SWEEP_POINT(s.start());
  511.      SWEEP_point q = new SWEEP_POINT(s.end());
  512.      seg = new SWEEP_SEGMENT(p,q,1,count--);
  513.      draw_segment(seg);
  514.      Xinsert(nil,get_startpoint(seg));
  515. /*
  516. Print(seg);
  517. Print(get_startpoint(seg));
  518. newline;
  519. */
  520.    }
  521.  
  522.  
  523.   count = 0;
  524.  
  525.   x_sweep = Wp->xmin();
  526.   y_sweep = Wp->ymin();
  527.  
  528.   if (trace)
  529.   { draw_Xstructure();
  530.     draw_Ystructure();
  531.    }
  532.  
  533.   draw_sweep_line(x_sweep);
  534.  
  535.   while(!X_structure.empty())
  536.   {
  537.     if (trace)  
  538.        trace = (Wp->read_mouse() != 3);
  539.     else
  540.        trace = Wp->get_button();
  541.  
  542.  
  543.     pxmin = X_structure.find_min();
  544.     p = X_structure.inf(pxmin);
  545.  
  546.     move_sweep_line(x_sweep,get_x(p));
  547.  
  548.     sitmin = X_structure.key(pxmin);
  549.  
  550.     Xdelete(pxmin);
  551.  
  552.  
  553.  
  554.     if (get_kind(p) == Leftend)
  555.  
  556.     //left endpoint
  557.     { 
  558.  
  559.       l = get_seg(p); 
  560.  
  561.       x_sweep = get_x(p);
  562.       y_sweep = get_y(p);
  563.  
  564.       if (trace)
  565.       message(string("LEFT  point   x = %4f seg = %4d",
  566.               get_x(p),get_name(l)),1);
  567.  
  568.  
  569.       if (get_x(p) == get_x(get_endpoint(l)))
  570.         process_vertical_segment(/*SUB,*/ l);
  571.       else
  572.       {
  573.  
  574.       sit = Y_structure.lookup(l);
  575.  
  576.       if (sit!=nil)  error_handler(0,"plane sweep: sorry, overlapping segments");
  577.  
  578.       sit = Y_structure.insert(l,nil);
  579.  
  580.       Xinsert(sit,get_endpoint(l));
  581.  
  582.       sitpred = Y_structure.pred(sit);
  583.       sitsucc = Y_structure.succ(sit);
  584.  
  585.       if (sitpred != nil) 
  586.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  587.           delete Xdelete(pqit);
  588.  
  589.         lpred = Y_structure.key(sitpred);
  590.  
  591.         Y_structure.change_inf(sitpred,nil);
  592.  
  593.         if (intersection(lpred,l,inter))
  594.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  595.       }
  596.  
  597.  
  598.       if (sitsucc != nil)
  599.       { lsucc = Y_structure.key(sitsucc);
  600.         if (intersection(lsucc,l,inter))
  601.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  602.       }
  603.      } /* else if vertical */
  604.  
  605.     }
  606.     else if (get_kind(p) == Rightend)
  607.          //right endpoint
  608.          { 
  609.            x_sweep = get_x(p);
  610.            y_sweep = get_y(p);
  611.  
  612.            if (trace)
  613.            message(string("RIGHT point   x = %4f seg = %4d",
  614.                    get_x(p),get_name(get_seg(p))),1);
  615.  
  616.            sit = sitmin;
  617.  
  618.            sitpred = Y_structure.pred(sit);
  619.            sitsucc = Y_structure.succ(sit);
  620.  
  621.            SWEEP_segment SEG =Y_structure.key(sit);
  622.  
  623.            Y_structure.del_item(sit);
  624.  
  625.            delete SEG;
  626.  
  627.            if((sitpred != nil)&&(sitsucc != nil))
  628.            {
  629.              lpred = Y_structure.key(sitpred);
  630.              lsucc = Y_structure.key(sitsucc);
  631.              if (intersection(lsucc,lpred,inter))
  632.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  633.            }
  634.          }
  635.          else /*point of intersection*/
  636.          { 
  637.            //node w = New_Node(SUB,get_x(p),get_y(p));
  638.  
  639.            count++;
  640.  
  641.            /* Let L = list of all lines intersecting in p 
  642.  
  643.               we compute sit     = L.head();
  644.               and        sitpred = L.tail();
  645.  
  646.               by scanning the Y_structure in both directions 
  647.               starting at sitmin;
  648.  
  649.            */
  650.  
  651.            /* search for sitpred upwards from sitmin: */
  652.  
  653.            Y_structure.change_inf(sitmin,nil);
  654.  
  655.            sitpred = Y_structure.succ(sitmin);
  656.  
  657.  
  658.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  659.            { SWEEP_point q = X_structure.inf(pqit);
  660.              if (compare(p,q) != 0) break; 
  661.              X_structure.del_item(pqit);
  662.              Y_structure.change_inf(sitpred,nil);
  663.              sitpred = Y_structure.succ(sitpred);
  664.             }
  665.  
  666.  
  667.            /* search for sit downwards from sitmin: */
  668.  
  669.            sit = sitmin;
  670.  
  671.            seq_item sit1;
  672.            
  673.            while ((sit1=Y_structure.pred(sit)) != nil)
  674.            { pqit = Y_structure.inf(sit1);
  675.              if (pqit == nil) break;
  676.              SWEEP_point q = X_structure.inf(pqit);
  677.              if (compare(p,q) != 0) break; 
  678.              X_structure.del_item(pqit);
  679.              Y_structure.change_inf(sit1,nil);
  680.              sit = sit1;
  681.             }
  682.  
  683.  
  684. /*
  685.            if (trace)
  686.            { string line;
  687.              line += string("sit = %d  ", get_name(Y_structure.key(sit)));
  688.              line += string("sitpred = %d",get_name(Y_structure.key(sitpred)));
  689.              message(line,5);
  690.             }
  691. */
  692.  
  693. /*
  694.  
  695.            // insert edges to p for all segments in sit, ..., sitpred into SUB
  696.            // and set left node to w 
  697.  
  698.            lsit = Y_structure.key(sitpred);
  699.  
  700.            node v = get_left_node(lsit);
  701.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  702.            set_left_node(lsit,w);
  703.  
  704.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  705.            { lsit = Y_structure.key(sit1);
  706.  
  707.              v = get_left_node(lsit);
  708.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  709.              set_left_node(lsit,w);
  710.             }
  711. */
  712.  
  713.            lsit = Y_structure.key(sit);
  714.            lpred=Y_structure.key(sitpred);
  715.            sitpredpred = Y_structure.pred(sit);
  716.            sitsucc=Y_structure.succ(sitpred);
  717.  
  718.            message(string("INTERSECTION  # = %4d  x = %5f  seg = %4d ",
  719.                         count, float(get_x(p)),get_name(lsit)),1);
  720.  
  721.            draw_sweep_line(get_x(p));
  722.            Wp->draw_filled_node(get_x(p),get_y(p),node_color);
  723.            draw_sweep_line(get_x(p));
  724.  
  725.  
  726.            if (sitpredpred != nil)
  727.             { 
  728.               lpredpred=Y_structure.key(sitpredpred);
  729.  
  730.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  731.                delete Xdelete(pqit);
  732.      
  733.  
  734.               Y_structure.change_inf(sitpredpred,nil);
  735.  
  736.  
  737.               if (intersection(lpred,lpredpred,inter))
  738.                 Y_structure.change_inf(sitpredpred,
  739.                                        Xinsert(sitpredpred,inter));
  740.              }
  741.  
  742.  
  743.            if (sitsucc != nil)
  744.             {
  745.               lsucc=Y_structure.key(sitsucc);
  746.  
  747.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  748.                 delete Xdelete(pqit);
  749.                  
  750.               Y_structure.change_inf(sitpred,nil);
  751.  
  752.               if (intersection(lsucc,lsit,inter))
  753.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  754.              }
  755.  
  756.  
  757. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  758.  
  759.            x_sweep = get_x(p);
  760.            y_sweep = get_y(p);
  761.  
  762.            Y_structure.reverse_items(sit,sitpred);
  763.  
  764.            delete p;
  765.  
  766.          } // intersection
  767.  
  768.    if (trace) 
  769.     { draw_Xstructure();
  770.       draw_Ystructure();
  771.      }
  772.  
  773.   }
  774.  
  775.   message("END OF SWEEP",1);
  776.  
  777.   if (intera) Wp->read_mouse();             //wait for mouse click
  778.  
  779.     draw_sweep_line(x_sweep);
  780.  
  781.     X_structure.clear();
  782.  
  783. } // plane_sweep
  784.  
  785.  
  786.  
  787. void interactive(window& W)
  788. {
  789.   intera= true;
  790.  
  791.   int grid_width = 0;
  792.   int line_width = 1;
  793.   int node_width = 4;
  794.   int N = 80;
  795.  
  796.   panel P("PLANE SWEEP DEMO");
  797.  
  798.   P.bool_item("TRACE",trace);
  799.   P.int_item("GRID",grid_width,0,40,10);
  800.   P.int_item("SEGMENTS", N);
  801.   P.int_item("line width",line_width,1,5);
  802.   P.int_item("node width",node_width,1,10);
  803.   P.button("MOUSE");
  804.   P.button("RANDOM");
  805.   P.button("QUIT");
  806.  
  807.   for(;;)
  808.   { int input = P.open(W);
  809.   
  810.     if (input == 2) break;
  811.   
  812.     W.init(-1200,1200,-1200, grid_width);
  813.     W.set_text_mode(opaque);
  814.     W.set_node_width(node_width);
  815.     W.set_line_width(line_width);
  816.   
  817.     list<segment> seglist1,seglist2;
  818.   
  819.     if (input==1)  // random 
  820.      { init_random();
  821.        double ymax = W.ymax()-4*20/W.scale()-100;
  822.        int xmin = int(W.xmin())+100;
  823.        int xmax = int(W.xmax())-100;
  824.        for(int i=0; i<N; i++)
  825.        { double x1 = random(xmin,-100);
  826.          double y1 = random(-1000,int(ymax));
  827.          double x2 = random(100,xmax);
  828.          double y2 = random(-1000,int(ymax));
  829.          segment s(x1,y1,x2,y2);
  830.          W << s;
  831.          seglist1.append(s);
  832.         }
  833.       }
  834.     else // input == 0 (mouse)
  835.       { segment s;
  836.         while (W >> s)
  837.         { W << s;
  838.           seglist1.append(s);
  839.          }
  840.        }
  841.   
  842.   
  843.     plane_sweep(seglist1,seglist2);
  844.   
  845.   //GRAPH<point,int> SUB;
  846.   //plane_sweep(seglist1,seglist2,SUB);
  847.   
  848.  } // for(;;)
  849.  
  850. }
  851.  
  852.  
  853.  
  854. void demo(window& W, int N)
  855. {
  856.   trace = false;
  857.  
  858.   W.init(-1200,1200,-1200);
  859.  
  860.   for(;;)
  861.   {
  862.  
  863.   W.clear();
  864.  
  865.  
  866.   W.set_text_mode(opaque);
  867.   W.set_node_width(3);
  868.  
  869.  
  870.   list<segment> seglist1,seglist2;
  871.  
  872.      init_random();
  873.  
  874.      double ymax = W.ymax()-4*20/W.scale()-100;
  875.  
  876.      for(int i=0; i<N; i++)
  877.      { double x1 = random(-1100,-100);
  878.        double y1 = random(-1000,int(ymax));
  879.        double x2 = random(100,1100);
  880.        double y2 = random(-1000,int(ymax));
  881.        segment s(x1,y1,x2,y2);
  882.        W << s;
  883.        seglist1.append(s);
  884.       }
  885.  
  886.   plane_sweep(seglist1,seglist2);
  887.  
  888. /*
  889.   GRAPH<point,int> SUB;
  890.   edge e;
  891.  
  892.   plane_sweep(seglist1,seglist2,SUB);
  893.  
  894.   W.clear();
  895.   forall_edges(e,SUB) W <<  segment(SUB[source(e)],SUB[target(e)]);
  896. */
  897.  
  898.   wait(2);
  899.  
  900.   }
  901.  
  902. }
  903.  
  904.  
  905. /*
  906. #include <LEDA/stream.h>
  907. */
  908.  
  909.  
  910. main(int argc, char** argv)
  911. {
  912.   int N = 0;
  913.  
  914.   if (argc == 1)
  915.   { panel P0("PLANE SWEEP DEMO");
  916.     P0.text_item("This program computes the intersections in a set of");
  917.     P0.text_item("straight line segments using a plane sweep algorithm.");
  918.     P0.text_item("You can define the set of line segments interactively");
  919.     P0.text_item("using the left mouse button (input is terminated with");
  920.     P0.text_item("the right button) or create a random set of segments.");
  921.     P0.text_item("In TRACE mode the current contents of the event queue");
  922.     P0.text_item("(X-structure) and of the sweep line (Y-structure) are");
  923.     P0.text_item("displayed and the sweep line stops at each event point.");
  924.     P0.button("continue");
  925.     P0.open();
  926.    }
  927.   else
  928.     N = atoi(argv[1]);
  929.  
  930.   window W;
  931.  
  932.   Wp = &W;
  933.  
  934.   if (N==0) 
  935.       interactive(W);
  936.   else
  937.      demo(W,N);
  938.  
  939.  
  940.   return 0;
  941. }
  942.